%option noyywrap
%{
#include <cmath>
#include <vector>
#include <cstring>
#include <cstdlib>  //对于 atof，如果使用 C 标准库
#include <string>  // 对于 std::stod
#include "../include/symtab.h"
#include "../parser/SysY_parser.tab.h"

extern int line_number;
extern int col_number;
extern int cur_col_number;
extern IdTable id_table;
void yyerror(char* s, ...);
%}


%x COMMENT

%%
    /* TODO():增加处理注释的代码*/

"//"[^\n]* { 
    /*更新列号*/ 
    col_number += strlen(yytext); 
}

"/*" {  
    col_number += strlen(yytext);
    BEGIN COMMENT;
}
<COMMENT>"*/" { 
    col_number += strlen(yytext); 
    BEGIN INITIAL;  
}
<COMMENT>\n { 
    ++line_number; 
    col_number = 0; 
}
<COMMENT>. { 
    /*匹配除换行符之外的任何单个字符*/
    col_number += strlen(yytext); 
}


    /* TODO():增加处理列号的代码(cur_col_number表示当前token开始位置, col_number表示当前token结束位置) */

"<=" {cur_col_number = col_number;col_number += strlen(yytext);return LEQ;}         
">=" {cur_col_number = col_number;col_number += strlen(yytext);return GEQ;}         
"==" {cur_col_number = col_number;col_number += strlen(yytext);return EQ;}        
"!=" {cur_col_number = col_number;col_number += strlen(yytext);return NE;}
"&&" {cur_col_number = col_number;col_number += strlen(yytext);return AND;}         
"||" {cur_col_number = col_number;col_number += strlen(yytext);return OR;}               
"const" {cur_col_number = col_number;col_number += strlen(yytext);return CONST;}     
"if" {cur_col_number = col_number;col_number += strlen(yytext);return IF;}       
"else" {cur_col_number = col_number;col_number += strlen(yytext);return ELSE;}  
"while" {cur_col_number = col_number;col_number += strlen(yytext);return WHILE;}
"void" {cur_col_number = col_number;col_number += strlen(yytext);return VOID;}    
"int" {cur_col_number = col_number;col_number += strlen(yytext);return INT;}    
"float" {cur_col_number = col_number;col_number += strlen(yytext);return FLOAT;}      
"return" {cur_col_number = col_number;col_number += strlen(yytext);return RETURN;}    
"break" {cur_col_number = col_number;col_number += strlen(yytext);return BREAK;}     
"continue" {cur_col_number = col_number;col_number += strlen(yytext);return CONTINUE;}

    /*行和列的处理*/

\n {++line_number;col_number = 0;}

[ \t\f\r\v] {col_number += strlen(yytext);}

    /*识别基本的运算符和标点符，返回的它自己与case里面的对应*/

[\.\+\-\*\/\=\<\!\%\>] {cur_col_number = col_number;col_number += strlen(yytext);return yytext[0];}

[\{\}\;\(\)\,\[\]] {cur_col_number = col_number;col_number += strlen(yytext);return yytext[0];}

    /*标识符处理*/

[_a-zA-Z][_a-zA-Z0-9]* {
    cur_col_number = col_number;
    col_number += strlen(yytext);
    yylval.symbol_token = id_table.add_id(std::string(yytext));
    return IDENT;
}

    /*十进制整数常量的处理*/
    /*
        int32位范围[−2147483648,2147483647]，对于-2147483648，一般词法分析是将2147483648和负号分开处理，
        但是2147483648超过了int的表示范围，编译器直接让该数溢出，不作任何处理，输出的值就是-2147483648。
        编译器可能会让整数在溢出时自然溢出，并在下次使用该整数时截断到类型的大小。
        一个32位的 int 类型溢出可能会回绕到其范围内的某个值，如2147483649输出的值为-2147483647
    */


([1-9][0-9]*)|0 {
    cur_col_number = col_number;
    col_number += strlen(yytext);
    // yylval.int_token = stoi(std::string(yytext));
    yylval.int_token = 0;
    for(int i = 0;yytext[i];i++){
        yylval.int_token *= 10;
        yylval.int_token += yytext[i] - '0';
    }
    return INT_CONST;
}
    /*
      在词法分析中，你只需要考虑yylval的三种类型，分别为int_token, float_token, symbol_token
      之所以要定义这三种类型，是因为我们只返回这个token的类型是不够的，我们还需要知道这个token的属性
      例如我们需要知道INT_CONST具体的值是多少
    */
    /*TODO():参考SysY2022定义, 处理更多的词法, 如浮点数，十六进制数等*/

    /*八进制整数常量的处理*/
    /*以数字0开始，后面跟着0到7之间的数字序列*/

0[0-7]* {
    cur_col_number = col_number;
    col_number += strlen(yytext);
    yylval.int_token = 0;
    for(int i = 0;yytext[i];i++){
        yylval.int_token *= 8;
        yylval.int_token += yytext[i] - '0';
    }
    return INT_CONST;
}

    /*十六进制整数常量的处理*/
    /*以0x或0X开始，后面跟着十六进制数字序列*/

0[xX][0-9a-fA-F]+ {
    cur_col_number = col_number;
    col_number += strlen(yytext);
    yylval.int_token = 0;
    //从索引2开始，跳过0x0X
    for (int i = 2; yytext[i]; i++) {  
        yylval.int_token *= 16;
        if (yytext[i] >= '0' && yytext[i] <= '9') {
            yylval.int_token += yytext[i] - '0';
        } else if (yytext[i] >= 'a' && yytext[i] <= 'f') {
            yylval.int_token += yytext[i] - 'a' + 10;
        } else if (yytext[i] >= 'A' && yytext[i] <= 'F') {
            yylval.int_token += yytext[i] - 'A' + 10;
        }
    }
    return INT_CONST;
}


    /*十进制指数的处理*/

[0-9]+[eE][+-]?[0-9]+ {
    cur_col_number = col_number;
    col_number += strlen(yytext);

    //处理整数部分

    double int_part = 0.0;
    int i=0;
    for (;yytext[i] != 'e' && yytext[i] != 'E'; ++i) {
        int_part = 10.0 * int_part + (yytext[i] - '0');
    }
    
    double value=int_part;
    //处理指数部分
    if (i < strlen(yytext) && (yytext[i] == 'e' || yytext[i] == 'E')) {
        i++; 
        int exp_sign=1;
        if (yytext[i] == '+' || yytext[i] == '-') {
            exp_sign = (yytext[i] == '-') ? -1 : 1;
            i++;
        }
        int multiplier1 = 0;
        for(;yytext[i];i++){
            multiplier1 =10*multiplier1+(yytext[i] - '0');
        }
        value=value*pow(10, exp_sign*multiplier1);
    }

    yylval.float_token = value;
    return FLOAT_CONST;

}

    /*十六进制指数的处理*/

0[xX][0-9a-fA-F]+[pP][+-]?[0-9]+ {
    cur_col_number = col_number;
    col_number += strlen(yytext);

    //从索引2开始，跳过0x0X
    int i = 2;

    //处理整数部分
    double int_part=0.0;
    for (; yytext[i] != 'p' && yytext[i] != 'P'; i++) {  
        int_part *= 16;
        if (yytext[i] >= '0' && yytext[i] <= '9') {
            int_part += yytext[i] - '0';
        } else if (yytext[i] >= 'a' && yytext[i] <= 'f') {
            int_part += yytext[i] - 'a' + 10;
        } else if (yytext[i] >= 'A' && yytext[i] <= 'F') {
            int_part += yytext[i] - 'A' + 10;
        }
    }
    double value=int_part;

    //处理指数部分
    if (i < strlen(yytext) && (yytext[i] == 'p' || yytext[i] == 'P')) {
        i++; 
        int exp_sign=1;
        if (yytext[i] == '+' || yytext[i] == '-') {
            exp_sign = (yytext[i] == '-') ? -1 : 1;
            i++;
        }
        int multiplier1 = 0;
        for(;yytext[i];i++){
            int_part *= 16;
            if (yytext[i] >= '0' && yytext[i] <= '9') {
                multiplier1 += yytext[i] - '0';
            } else if (yytext[i] >= 'a' && yytext[i] <= 'f') {
                multiplier1 += yytext[i] - 'a' + 10;
            } else if (yytext[i] >= 'A' && yytext[i] <= 'F') {
                multiplier1 += yytext[i] - 'A' + 10;
            }
        }
        value=value*pow(2, exp_sign*multiplier1);
        
    }

    yylval.float_token = value;
    return FLOAT_CONST;

}




    /*十进制浮点数常量的处理*/

[0-9]*[.][0-9]*([eE][+-]?[0-9]+)? {
    cur_col_number = col_number;
    col_number += strlen(yytext);

    yylval.float_token = std::stod(yytext);
    return FLOAT_CONST;
}



    /*十六进制浮点数常量的处理*/

0[xX][0-9a-fA-F]*[.][0-9a-fA-F]*([pP][+-]?[0-9]+)? {
    cur_col_number = col_number;
    col_number += strlen(yytext);

    //从索引2开始，跳过0x0X
    int i = 2;

    //处理整数部分
    double int_part=0.0;
    for (; yytext[i] != '.'; i++) {  
        int_part *= 16;
        if (yytext[i] >= '0' && yytext[i] <= '9') {
            int_part += yytext[i] - '0';
        } else if (yytext[i] >= 'a' && yytext[i] <= 'f') {
            int_part += yytext[i] - 'a' + 10;
        } else if (yytext[i] >= 'A' && yytext[i] <= 'F') {
            int_part += yytext[i] - 'A' + 10;
        }
    }

    //处理小数部分
    double frac_part = 0.0;
    double multiplier = 0.0625;
    if (i < strlen(yytext) && yytext[i] == '.') {
        i++;
        for (; i < strlen(yytext) && yytext[i] != 'p' && yytext[i] != 'P'; ++i) {
            if (yytext[i] >= '0' && yytext[i] <= '9') {
                frac_part+=(yytext[i] - '0')*multiplier;
            } else if (yytext[i] >= 'a' && yytext[i] <= 'f') {
                frac_part+=(yytext[i] - 'a' + 10)*multiplier;
            } else if (yytext[i] >= 'A' && yytext[i] <= 'F') {
                frac_part+=(yytext[i] - 'A' + 10)*multiplier;
            }
            multiplier*=0.0625;
        }
    }
    double value= int_part + frac_part;

    //处理指数部分
    if (i < strlen(yytext) && (yytext[i] == 'p' || yytext[i] == 'P')) {
        i++; 
        int exp_sign=1;
        if (yytext[i] == '+' || yytext[i] == '-') {
            exp_sign = (yytext[i] == '-') ? -1 : 1;
            i++;
        }
        int multiplier1 = 0;
        for(;yytext[i];i++){
            int_part *= 16;
            if (yytext[i] >= '0' && yytext[i] <= '9') {
                multiplier1 += yytext[i] - '0';
            } else if (yytext[i] >= 'a' && yytext[i] <= 'f') {
                multiplier1 += yytext[i] - 'a' + 10;
            } else if (yytext[i] >= 'A' && yytext[i] <= 'F') {
                multiplier1 += yytext[i] - 'A' + 10;
            }
        }
        value=value*pow(2, exp_sign*multiplier1);
        
    }

    yylval.float_token = value;
    return FLOAT_CONST;

}
    

    /*unknown tokens, return ERROR*/
. {
    cur_col_number = col_number;
    col_number += strlen(yytext);
    yylval.error_msg = yytext;
    return ERROR;
}
%%



